package com.yjzx.util.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author yjzx
 * @date 2024/05/27
 * @description 时间表
 */
public class TimeUtils {
    public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat sdfStamp = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    public static final SimpleDateFormat sdf_y_m_d = new SimpleDateFormat("yyyy-MM-dd");
    public static final SimpleDateFormat sdf_ymd = new SimpleDateFormat("yyyyMMdd");
    public static final SimpleDateFormat sdf_y_m = new SimpleDateFormat("yyyy-MM");
    public static final SimpleDateFormat sdf_h_m_s = new SimpleDateFormat("HH:mm:ss");
    /**
     * 时间格式化,LocalDatetime
     */
    public static final DateTimeFormatter DATETIME_YMD_FMT = new DateTimeFormatterBuilder().append(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
            .toFormatter();

    /**
     * 根据开始时间和结束时间，判断当前状态是否完整
     *
     * @param b 开始时间
     * @param e 结束时间
     * @return 0 未开始
     * 1 进行中
     * 2 已结束
     */
    public static short check(Date b, Date e) {
        long current = System.currentTimeMillis();
        //小于开始时间 还未开始
        if (current < b.getTime()) {
            return (short) 0;
        }
        //大于等于开始时间 小于结束时间 （进行中）
        else if (current < e.getTime()) {
            return (short) 1;
        }
        //已经结束
        return (short) 2;
    }




    /**
     * 获取某一天的结束时间
     *
     * @param date
     * @return
     */
    public static Date getOneDayEndTime(Date date) {
        LocalDate localDate = TimeUtils.dateToLocalDate(date);
        return Date.from(LocalDateTime.of(localDate, LocalTime.MAX).atZone(
                ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取某一天的开始时间
     *
     * @param date
     * @return
     */
    public static Date getOneDayBeginTime(Date date) {
        LocalDate localDate = TimeUtils.dateToLocalDate(date);
        return Date.from(LocalDateTime.of(localDate, LocalTime.MIN).atZone(
                ZoneId.systemDefault()).toInstant());
    }

    /**
     * Date转 y_m_d 时间字符串
     *
     * @param time
     * @return
     */
    public static String dateToString(Date time) {
        return sdf_y_m_d.format(time);
    }
    /**
     * Date转 HH:mm:ss 时间字符串
     *
     * @param time
     * @return
     */
    public static String dateTimeToString(Date time) {
        return sdf.format(time);
    }
    public static String timeToString(Date time) {
        return sdf_h_m_s.format(time);
    }




    /**
     * "yyyy-MM-dd HH:mm:ss" 时间字符串转 Date
     *
     * @param str
     * @return
     */
    public static Date stringToDateTime(String str) {
        if (StringUtils.isNotBlank(str)) {
            try {
                return sdf.parse(str);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * "yyyy-MM-dd" 时间字符串转 Date
     *
     * @param str
     * @return
     */
    public static Date stringToDate(String str) {
        if (StringUtils.isNotBlank(str)) {
            try {
                return sdf_y_m_d.parse(str);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    /**
     * "HH:mm:ss" 时间字符串转 Date
     *
     * @param time
     * @return
     */
    public static Date stringToTime(String time) {
        try {
            return sdf_h_m_s.parse(time);
        } catch (ParseException e) {
            throw new RuntimeException("时间转换异常");
        }
    }
    /**
     * Date 转 LocalTime 包含时区转换
     *
     * @param date
     * @return
     */
    public static LocalTime newDateToLocalTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
    }

    /**
     * Date 转 LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate dateToLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }
    /**
     * Date 转 LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }
    /**
     * LocalDate 转 Date
     *
     * @param localDate
     * @return
     */
    public static Date localDateToDate(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }
    /**
     * LocalDateTime 转 Date
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }








    public static Boolean checkDuration(String beginTime, String endTime, long maxDays) {
        long duration = stringToDateTime(endTime).getTime() - stringToDateTime(beginTime).getTime();
        if (duration > maxDays * 24 * 60 * 60 * 1000) {
            return true;
        } else {
            return false;
        }
    }

    public static String getTimeStamp() {
        return sdfStamp.format(new Date());
    }

    /**
     * 将第一个时间的日期和第二个日期的时间合并为一个日期
     * @param date
     * @param time
     * @return
     */
    public static Date assembleDateAndTime(Date date, Date time) {
        LocalDate localDate = TimeUtils.dateToLocalDate(date);
        LocalTime localTime = TimeUtils.newDateToLocalTime(time);
        LocalDateTime localDateTime = LocalDateTime.of(localDate.getYear(), localDate.getMonth(), localDate.getDayOfMonth(), localTime.getHour(), localTime.getMinute(), localTime.getSecond());
        return TimeUtils.localDateTimeToDate(localDateTime);
    }




    /**
     * 获取两天之间的连续天
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return 开始与结束之间的所以日期，包括起止
     */
    public static List<Date> getBetweenDates(Date startDate, Date endDate) {
        LocalDate begin = dateToLocalDate(startDate);
        LocalDate end = dateToLocalDate(endDate);
        List<Date> dates = new ArrayList<>();
        while (begin.isBefore(end)) {
            dates.add(localDateToDate(begin));
        }
        dates.add(localDateToDate(end));
        return dates;
    }

    /**
     * 获取两个时间之间的月份
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<Date> getBetweenMonths(Date startDate, Date endDate) {
        LocalDate begin = TimeUtils.dateToLocalDate(startDate).withDayOfMonth(1);
        LocalDate end = TimeUtils.dateToLocalDate(endDate).withDayOfMonth(1);
        List<Date> months = new ArrayList<>();
        while (begin.isBefore(end)) {
            months.add(localDateToDate(begin));
        }
        months.add(localDateToDate(end));
        return months;
    }
    /**
     * 获取两个时间之间的年份
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<Date> getBetweenYears(Date startDate, Date endDate) {
        LocalDate begin = dateToLocalDate(startDate).withMonth(1).withDayOfMonth(1);
        LocalDate end = dateToLocalDate(endDate).withMonth(1).withDayOfMonth(1);
        List<Date> years = new ArrayList<>();
        while (begin.isBefore(end)) {
            years.add(localDateToDate(begin));
            begin = begin.plusYears(1);
        }
        years.add(localDateToDate(end));
        return years;
    }


    /**
     * 去除时分秒
     *
     * @param date
     * @return
     */
    public static Date getSpecificDate(Date date) {
        long createTime = System.currentTimeMillis();
        long time = createTime - ((createTime + 28800000) % (86400000));
        return new Date(time);
    }


    /**
     * 按格式获取日期
     *
     * @param date
     * @return
     */
    public static String getDateByFormat(Date date, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }
    /**
     * 时间加月
     *
     * @param date
     * @return
     */
    public static Date dateToStringTimeAddSomeMonth(Date date, Integer n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, n);
        return calendar.getTime();
    }
    /**
     * 时间加n天
     *
     * @param date
     * @return
     */
    public static Date dateToStringTimeAddSomeDay(Date date, Integer n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, n);
        return calendar.getTime();
    }


    /**
     * 将string 时间加n分钟 返回字符串
     *
     * @param date+10
     * @return
     */
    public static String dateToStringTimeAddSomeMin(Date date, Integer n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, n);
        return dateTimeToString(calendar.getTime());
    }

    /**
     * 将时间加n秒 返回字符串
     *
     * @param date+10
     * @return
     */
    public static Date dateAddSomeSeconds(Date date, Integer n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, n);
        return calendar.getTime();
    }

}
